package com.bilibili.service.impl;

import com.bilibili.entity.User;
import com.bilibili.exception.BusinessException;
import com.bilibili.manage.SmsService;
import com.bilibili.mapper.UserMapper;
import com.bilibili.service.UserService;
import com.bilibili.utils.RandomUtils;
import com.bilibili.utils.RedisOperations;
import com.bilibili.vo.UserLoginVo;
import com.bilibili.vo.UserRegistVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.Objects;

import static com.bilibili.constant.BusinessConstant.*;
import static com.bilibili.constant.RegexConstant.PHONE_REGEX;
import static com.bilibili.constant.RegexConstant.STRONG_PWD_REGEX;


@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SmsService smsService;
    @Autowired
    private RedisOperations redisOperations;

    @Override
    public User getUserByUserName(String userName) {
        User user = userMapper.getUserByUserName(userName);
        if (Objects.isNull(user)) {
            throw new BusinessException(HttpStatus.NOT_FOUND, "昵称不存在");
        }
        return user;
    }

    @Override
    public boolean isUserNameExists(String userName) {
        return !Objects.isNull(getUserByUserName(userName));
    }

    @Override
    public boolean isPhoneExists(String phone) {
        boolean exists = userMapper.getUserByPhone(phone);
        if (!exists) {
            throw new BusinessException(HttpStatus.NOT_FOUND, "手机号不存在");
        }
        return true;
    }

    @Override
    public boolean sendValidateCode(String phone) {
        //手机号非空
        if (StringUtils.isBlank(phone)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号不能为空");
        }
        //手机号是否合法
        if (!phone.matches(PHONE_REGEX)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号格式不合法");
        }
        //生成验证码
        String code = RandomUtils.generateValidateCode(VALIDATE_CODE_LENGTH);
        boolean smsSuccess = smsService.sendValidateCode(phone, code);
        if (!smsSuccess) {
            throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR, "短信发送失败！");
        } else {
            String key = REDIS_VALIDATE_CODE_PREFIX + phone;
            redisOperations.set(key, code);
            redisOperations.expire(key, VALIDATE_CODE_EXPIRE_SECONDS);
        }
        return true;
    }

    @Override
    public User regist(UserRegistVo userRegistVo) {
        String phone = userRegistVo.getPhone();
        String userName = userRegistVo.getUserName();
        String userPwd = userRegistVo.getUserPwd();
        String validateCode = userRegistVo.getValidateCode();
        //用户名非空
        if (StringUtils.isBlank(userName)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "用户名不能为空");
        }
        //用户名重复
        if (!Objects.isNull(userMapper.getUserByUserName(userName))) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "用户名已存在");
        }
        //密码不能为空
        if (StringUtils.isBlank(userPwd)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "密码不能为空");
        }
        //密码必须是强类型
        if (!userPwd.matches(STRONG_PWD_REGEX)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "密码必须是强密码类型");
        }
        //手机号非空
        if (StringUtils.isBlank(phone)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号不能为空");
        }
        //手机号格式
        if (!phone.matches(PHONE_REGEX)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号格式不合法");
        }
        //手机号重复性
        if (userMapper.getUserByPhone(phone)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号已存在");
        }
        //验证码是否为空
        if (StringUtils.isBlank(validateCode)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "验证码不能为空");
        }
        //验证码是否和实际发送到手机的一致
        //判断验证码是否正确
        isValidateCodeCorrect(phone, validateCode);
        //(2-2)用户输入的和Redis中的相等-正确情况，可以继续做后面的逻辑
        User user = new User();
        user.setName(userName);
        user.setPwd(DigestUtils.md5Hex(userPwd));
        user.setPhone(phone);
        boolean success = userMapper.addUser(user);
        if (success) {
            user.setPwd(null);
            return user;
        } else {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "注册用户失败");
        }
    }

    @Override
    public User login(UserLoginVo userLoginVo) {
        //1.解析数据
        String phoneOrEmail = userLoginVo.getPhoneOrEmail();
        String userPwd = userLoginVo.getUserPwd();
        String phone = userLoginVo.getPhone();
        String validateCode = userLoginVo.getValidateCode();
        boolean loginByPwd = userLoginVo.isLoginByPwd();
        boolean rememberPwd = userLoginVo.isRememberPwd();
        //2.参数校验
        User user = null;
        //密码登录
        if (loginByPwd) {
            //手机号或邮箱进行验证
            if (StringUtils.isBlank(phoneOrEmail)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号或邮箱不能为空");
            }
            if (StringUtils.isBlank(userPwd)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "用户名密码不能为空");
            }
            user = userMapper.getUserByPhoneOrEmail(phoneOrEmail);
            if (Objects.isNull(user)) {
                throw new BusinessException(HttpStatus.NOT_FOUND, "用户不存在");
            }
            if (!StringUtils.equals(DigestUtils.md5Hex(userPwd), user.getPwd())) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "密码错误");
            }
        }
        //手机号和验证码登录
        else {
            //手机号和验证码进行验证
            if (StringUtils.isBlank(phone)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号不能为空");
            }
            if (StringUtils.isBlank(validateCode)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "验证码不能为空");
            }
            if (!userMapper.getUserByPhone(phone)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "手机号不存在");
            }
            //判断验证码是否正确
            isValidateCodeCorrect(phone, validateCode);
            user = userMapper.getUserByPhoneOrEmail(phone);
        }
        if(Objects.isNull(user)){
            throw new BusinessException(HttpStatus.BAD_REQUEST, "用户不存在");
        }
        user.setPwd(null);
        return user;
    }

    /**
     * 判断该手机号验证码是否正确
     *
     * @param phone
     * @return
     */
    public boolean isValidateCodeCorrect(String phone, String validateCode) {
        //验证码是否和实际发送到手机的一致
        //从Redis中获取当前手机号对应的验证码的信息
        String correctValidateCode = redisOperations.get(REDIS_VALIDATE_CODE_PREFIX + phone);
        //(1)从Redis中没有获取到当前手机号对应的验证码信息-验证码可能失效了（或者压根没法）
        if (StringUtils.isBlank(correctValidateCode)) {
            throw new BusinessException(HttpStatus.BAD_REQUEST, "验证码可能已经失效了，请重新发送~");
        }
        //(2)从Redis中获取到手机号对应的验证码信息
        else {
            //(2-1)用户输入的和Redis中的不相等-验证码输入错误的情况
            if (!StringUtils.equals(correctValidateCode, validateCode)) {
                throw new BusinessException(HttpStatus.BAD_REQUEST, "验证码错误~");
            }
        }
        return true;
    }
}
